/* FileExplorer.java
 * Author: liuex
 * 2007-12-20 ����09:27:21
 *
 * Note: 
 */
package lex.explorer.file;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.Collections;

import javax.swing.JTable;
import javax.swing.SortOrder;
import javax.swing.RowSorter.SortKey;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableRowSorter;

import org.lex.catalog.CatalogEvent;
import org.lex.explorer.FileInfo;
import org.lex.explorer.file.FileExplorer;
import org.lex.explorer.file.FileNameComparator;
import org.lex.explorer.file.FileNameRenderer;
import org.lex.explorer.file.FileSizeComparator;
import org.lex.explorer.file.FileTableModel;
import org.lex.explorer.file.SizeRenderer;
import org.lex.explorer.file.TablePopupMenu;
import org.lex.explorer.model.DefaultFileSystemModel;
import org.lex.explorer.model.FileSystemModel;
import org.lex.swing.Swings;
import org.lex.swing.table.DateRenderer;
import org.lex.swing.table.DefaultRenderer;
import org.lex.utils.Comparators;
import org.lex.utils.SystemProperties;

import lex.explorer.IExplorer;

public class FileExplorer extends JTable implements IExplorer
{
	private FileTableModel tableModel = null;
	private FileSystemModel fileModel = null;
	private TablePopupMenu popupMenu = null;

	public static void main( String[] args )
	{
		Swings.show( new FileExplorer( "C:\\") );
	}

	public FileExplorer()
	{
		this( new File( SystemProperties.userHome() ) );
	}

	public FileExplorer( String dir )
	{
		this( new File( dir ) );
	}

	public FileExplorer( File directory )
	{
		this( new DefaultFileSystemModel( directory ) );
	}

	public FileExplorer( FileSystemModel fileModel )
	{
		super();
		this.initialize();
		if( null == fileModel )
		{
			fileModel = new DefaultFileSystemModel( new File( "." ) );
			fileModel.reload();
		}
		this.setFileModel( fileModel );
		fileModel.reload();
	}

	public FileSystemModel getFileModel()
	{
		return this.fileModel;
	}

	public void setFileModel( FileSystemModel model )
	{
		if( null != this.fileModel )
			this.fileModel.removeCatalogListener( this );
		this.fileModel = model;
		this.fileModel.addCatalogListener( this );
		this.catalogChanged( new CatalogEvent( model, model.getCatalog() ) );
	}

	public void catalogChanged( CatalogEvent e )
	{
		this.getModel().setContent( this.getFileModel().getChildren() );
	}

	public FileInfo getSelectedFileInfo()
	{
		int row = this.getSelectedRow();
		if( row < 0 )
			return null;
		row = this.convertRowIndexToModel( row );
		return getModel().getFileInfo( row );
	}

	public File getSelectedFile()
	{
		int row = this.getSelectedRow();
		if( row < 0 )
			return null;
		row = this.convertRowIndexToModel( row );
		return getModel().getFile( row );
	}

	public int getSelectedItemsCount()
	{
		return this.getSelectedRowCount();
	}

	public File[] getSelectedFiles()
	{
		int[] rows = this.getSelectedRows();
		if( 0 == rows.length )
			return new File[0];
		File[] files = new File[rows.length];
		FileTableModel model = this.getModel();
		for( int i = 0; i < rows.length; i++ )
		{
			rows[i] = this.convertRowIndexToModel( rows[i] );
			files[i] = model.getFile( rows[i] );
		}
		return files;
	}

	public TablePopupMenu getPopupMenu()
	{
		if( null == popupMenu )
			popupMenu = new TablePopupMenu( this );
		return popupMenu;
	}

	@Override
	public FileTableModel getModel()
	{
		if( null == this.tableModel )
		{
			this.tableModel = new FileTableModel();
		}
		return this.tableModel;
	}

	private void initialize()
	{
		// initialize table
		this.setName( this.getClass().getName() + ".table" );
		this.setFillsViewportHeight( true );
		this.setShowGrid( false );
		this.setCellSelectionEnabled( true );
		this.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
		this.setModel( this.getModel() );
		// table double-click handler
		this.addMouseListener( new MouseAdapter(){
			@Override
			public void mouseClicked( MouseEvent e )
			{
				if( MouseEvent.BUTTON1 != e.getButton() )
					return;
				if( e.getClickCount() < 2 )
					return;
				FileInfo info = getSelectedFileInfo();
				if( null == info )
					return;
				File file = info.getFile();
				if( null == file || false == file.exists() || false == file.isDirectory() )
					return;
				getFileModel().setCatalog( info );
			}
		} );
		// setup column width, renderer, etc
		TableCellRenderer[] renderers = new TableCellRenderer[]{ new FileNameRenderer(),
				new SizeRenderer(), DefaultRenderer.getInstance(), new DateRenderer(),
				DefaultRenderer.getInstance() };
		int[] cellWidth = { 225, 85, 125, 150, 85 };
		TableColumnModel model = this.getColumnModel();
		for( int i = 0; i < renderers.length; i++ )
		{
			TableColumn column = model.getColumn( i );
			column.setPreferredWidth( cellWidth[i] );
			if( null != renderers[i] )
				column.setCellRenderer( renderers[i] );
		}
		this.getColumnModel().setColumnMargin( 5 );
		// add sorter
		TableRowSorter<FileTableModel> sorter = null;
		sorter = new TableRowSorter<FileTableModel>( getModel() );
		sorter.setComparator( 0, Comparators.newComparator( new FileNameComparator() ) );
		sorter.setComparator( 1, Comparators.newComparator( new FileSizeComparator() ) );
		sorter.setSortKeys( Collections.singletonList( new SortKey( 0, SortOrder.ASCENDING ) ) );
		this.setRowSorter( sorter );
		// set popup menu
		this.setComponentPopupMenu( this.getPopupMenu() );
	}
}
